// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/ktime.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/of.h>
#include <asm/byteorder.h>
#include <asm/switch_to.h>
#include <asm/unaligned.h>
#include <linux/of_device.h>

#include "hiusb_ont.h"

#define USB2_PHY0_BASE_82T          (0x10167000)
#define USB2_PHY_PORT_OFFSET_82T    (0x1000)

#define USB2_PHY_BASE_GET_82T(_phy_)    (USB2_PHY0_BASE_82T + USB2_PHY_PORT_OFFSET_82T * (_phy_))

#define USB2_PHY_ANA_CFG0                       (0x0)
#define USB2_PHY_ANA_CFG1                       (0x4)
#define USB2_PHY_ANA_CFG2                       (0x8)
#define USB2_PHY_ANA_CFG3                       (0xC)
#define USB2_PHY_ANA_CFG4                       (0x10)
#define USB2_PHY_ANA_CFG5                       (0x14)
#define USB2_PHY_PHY_CRG0                       (0x100)

#define USB2_PHY_ANA_CFG0_RG_HSTX_DEEN          (0x1UL << 5)
#define USB2_PHY_ANA_CFG0_RG_HSTX_DE_POS        (8)
#define USB2_PHY_ANA_CFG0_RG_HSTX_DE_MSK        (0xFUL << USB2_PHY_ANA_CFG0_RG_HSTX_DE_POS)

#define USB2_PHY_ANA_CFG2_RG_TEST_TX_POS        (20)
#define USB2_PHY_ANA_CFG2_RG_TEST_TX_MSK        (0xFFUL << USB2_PHY_ANA_CFG2_RG_TEST_TX_POS)

#define USB2_PHY_ANA_CFG2_RG_RT_TRIM_POS        (8)
#define USB2_PHY_ANA_CFG2_RG_RT_TRIM_MSK        (0x1FUL << USB2_PHY_ANA_CFG2_RG_RT_TRIM_POS)

#define USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_POS     (4)
#define USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_MSK     (0x7UL << USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_POS)
#define USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_410MV   (0x5UL << USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_POS)

#define ACP_SUBSYS_CTRL_82T                         (0x10100174)
#define ACP_SUBSYS_CTRL_82T_USB3_ACP_HIGH_ADDR_EN   (0x1UL << 27)

 /* USB0_PWREN: GPIO_43、USB1_PWREN: GPIO_44 */
#define USB_CLK_EN_82T_GEN3_PHY     ((0x1UL << 20) | (0x1UL << 19) | (0x1UL << 18) | (0x1UL << 17))
#define USB_CLK_EN_82T_GEN2_PHY     ((0x1UL << 6) | (0x1UL << 5))
#define USB_CLK_EN_82T_CTRL_APB     ((0x1UL << 22) | (0x1UL << 21))
#define USB_CLK_ENABLE_82T \
	(USB_CLK_EN_82T_GEN3_PHY | USB_CLK_EN_82T_GEN2_PHY | USB_CLK_EN_82T_CTRL_APB)

#define USB_PHY_CLK_ENABLE_82T      ((0x1UL << 8) | (0x1UL << 7) | (0x1UL << 5))

#define USB_PHY_POR_SRSTN_82T_GEN3  ((0x1UL << 30) | (0x1UL << 26) | (0x1UL << 19))
#define USB_PHY_POR_SRSTN_82T_GEN2  ((0x1UL << 28) | (0x1UL << 24))
#define USB_PHY_POR_UNRESET_82T     (USB_PHY_POR_SRSTN_82T_GEN3 | USB_PHY_POR_SRSTN_82T_GEN2)

#define USB_PHY_PORT_SRSTN_82T_GEN3 ((0x1UL << 31) | (0x1UL << 27))
#define USB_PHY_PORT_SRSTN_82T_GEN2 ((0x1UL << 29) | (0x1UL << 25))
#define USB_PHY_PORT_UNRESET_82T    (USB_PHY_PORT_SRSTN_82T_GEN3 | USB_PHY_PORT_SRSTN_82T_GEN2)

#define USB_APB_UNRESET_82T \
	((0x1UL << 22) | (0x1UL << 9) | (0x1UL << 8) | (0x1UL << 7) | (0x1UL << 6))
#define USB_CTRL_UNRESET_82T        (0x1UL << 21)

#define USB_CLK_ENABLE_82T_GEN2       (USB_CLK_EN_82T_GEN2_PHY | USB_CLK_EN_82T_CTRL_APB)
#define USB_PHY_POR_UNRESET_82T_GEN2  USB_PHY_POR_SRSTN_82T_GEN2
#define USB_PHY_PORT_UNRESET_82T_GEN2 USB_PHY_PORT_SRSTN_82T_GEN2

#define   IOMUX_SEL_PHY0_ADDR      (0x10100154)              // IOMUX_SEL_USB_PHY0 base addr
#define   IOMUX_SEL_PHY1_ADDR      (0x10100158)              // IOMUX_SEL_USB_PHY1 base addr
#define   IOMUX_SEL0_ADDR          (0x13000000)              // IOMUX_SEL0 base addr
#define   GPIO0_CTL_ADDR           (0x10106008)
#define   GPIO1_CTL_ADDR           (0x10107008)
#define   GPIO2_CTL_ADDR           (0x10108008)

/*define in SD5610*/
#define HI_SC_PEREN0               (0x14880014)
#define HI_SC_PERDIS0              (0x14880018)
#define HI_SC_PEREN1               (0x14880020)
#define HI_SC_PERDIS1              (0x14880024)
#define HI_SC_RST_CTRL0            (0x1488002c)

#define USB3_PERIPHCTRL0_ADDR      (0x1010009c)
#define USB3_PERI_GRXTHRCFG_ADDR   (0x1060C10C)
#define HI_GUSB3PIPECTL0           (0x10a5c2c0)
#define HI_GUSB3PIPECTL1           (0x10a5c2c1)

#define HI_1156_FST_S_SRST_UPSPHY_0    (0x11819410)
#define HI_1156_FST_S_GATE_EN_UPSPHY_0 (0x11819210)

#define HI_1156_FST_N_GATE_EN_USB2_1   (0x1191b208)
#define HI_1156_FST_S_GATE_EN_USB0     (0x11819208)

#define HI_1156_FST_N_SRST_USB2_1      (0x1191b408)
#define HI_1156_FST_S_SRST_USB0        (0x11819408)

#define HI_1156_FST_S_FREQ_CTRL_USB    (0x11819610)
#define HI_1156_USB3_CTRL_CTRL1        (0x50400c04)
#define HI_1156_FST_S_UPS_CTL0         (0x11814500)
#define HI_1156_FST_S_UPS_CTL1         (0x11814504)
#define HI_1156_FST_S_UPS_CTL2         (0x11814508)

#define HI_1155_FST_N_SRST_UPSPHY_1    (0x1191b410)
#define HI_1155_FST_N_GATE_EN_UPSPHY_1 (0x1191b210)

#define HI_1155_FST_N_GATE_EN_USB2_1   (0x11819208)
#define HI_1155_FST_S_GATE_EN_USB0     (0x1191b208)

#define HI_1155_FST_N_SRST_USB2_1      (0x11819408)
#define HI_1155_FST_S_SRST_USB0        (0x1191b408)

#define HI_1155_FST_N_FREQ_CTRL_USB    (0x1191b610)
#define HI_1155_USB3_CTRL_CTRL1        (0x50400c04)
#define HI_1155_FST_N_UPS_CTL0         (0x11914500)
#define HI_1155_FST_N_UPS_CTL1         (0x11914504)
#define HI_1155_FST_N_UPS_CTL2         (0x11914508)

#define FASTIO_S (0x11812000)
#define FASTIO_N (0x11912000)
#define ANA_CFG1 (0x4)
#define PHY_CRG0 (0x100)
#define ANA_CFG5 (0x14)
#define CKDT_STS (0x314)

#define HI_1156_USB2PHY_ADDR(base, reg) ((base) + (reg))

#define HI_1156_USB2_CLK_EN ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))
#define HI_1156_USB2_RST ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6))

#define HI_1156_USB3_CLK_EN ((1 << 0) | (1 << 1) | (1 << 3) | \
	(1 << 5) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11))
#define HI_1156_USB3_RST ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 7) | (1 << 9))
#define HI_1156_USB3_UPSPHY_CLK_EN ((1 << 0) | (1 << 1))
#define HI_1156_USB3_UPSPHY_RST ((1 << 0) | (1 << 1))

#define PLL_LOCK_TIMEOUT (10000)
#define PLL_LOCK_DELAY   (1)

/*chang in SD5115SH */
#define   USB_PWERN0              (1<<7)                  // USB_PWERN0
#define   USB_OVRCUR0             (1<<8)                  // USB_OVRCUR0
#define   USB_PWERN1              (1<<14)                 // USB_PWERN1
#define   USB_OVRCUR1             (1<<15)                 // USB_OVRCUR1

/*chang in SD5115T */
#define   USB_VBUS0               (1<<15)                  // USB_VBUS0
#define   USB_VBUS1               (1<<16)                  // USB_VBUS1

#define   PERI_PEREN_ADDR         (0x10100000 + 0x7C)      // PERI_PEREN base addr
#define   USB_HCLK_EN             (1<<16)                  // (1) for timer on

#define   PERI_PEREN1_ADDR        (0x10100000 + 0x8C)      // PERI_PEREN1 base addr
#define   USB_CLK_EN              (1<<22)                  // (1) for timer on

#define   PERI_PERCTRL36_ADDR      (0x10100000 + 0x12C)    // PERI_PERCTRL36 base addr
#define   USB_PORT1_RST            (1<<18)                 // (0):reset; (1): not reset
#define   USB_PORT0_RST            (1<<17)
#define   USB_CTRL_RST             (1<<16)
#define   USB_SRST                 (1<<15)

#define   PERI_PERCTRL39_ADDR      (0x10100000 + 0x138)    // PERI_PERCTRL39 base addr
#define   USB_PHY1_RST             (1<<1)                  // (0):reset; (1): not reset
#define   USB_PHY0_RST             (1<<0)

#define ECS_TZPC_BASE              (0x10101000)            // TZPC space, (4k)

#define BIT_SET(reg, bit) ((reg) |= (bit))                       // set BIT as (1)
#define BIT_CLR(reg, bit) ((reg) &= (~((unsigned int)(bit))))    // set BIT as (0)

#define USB3_MISC_CTRL_PHY_CRDATAIN         (0xFFFFUL << 16)
#define USB3_MISC_CTRL_PHY_CRPADDR          (0x1UL << 15)
#define USB3_MISC_CTRL_PHY_CRCAPDATA        (0x1UL << 14)
#define USB3_MISC_CTRL_PHY_CRREAD           (0x1UL << 13)
#define USB3_MISC_CTRL_PHY_CRWRITE          (0x1UL << 12)

#define USB3_MISC_STAT_PHY_CRACK            (0x1UL << 16)
#define USB3_MISC_STAT_PHY_CRDATAOUT        (0xFFFFUL)

#define HI_2952_FST_N_GATE_EN_USB2_1        (0x1191b248)
#define HI_2952_FST_N_SRST_USB2_0           (0x1191b444)

#define HI_2952_FST_S_GATE_EN_USB0          (0x1191b208)
#define HI_2952_FST_S_SRST_USB0             (0x1191b408)

#define HI_2952_UPS_CTL1                    (0x11914504)
#define HI_2952_FST_S_UPS_CTL0              (0x11914500)
#define HI_2952_FST_S_UPS_CTL2              (0x11914508)
#define HI_2952_FST_S_GATE_EN_UPSPHY_0      (0x1191b240)
#define HI_2952_FST_S_SRST_UPSPHY_0         (0x1191b448)

#define HI_2952_H6CC_CSR17                  (0x11940044)
#define HI_2952_H6CC_CSR22                  (0x11940058)

#define HI_2952_ANA_CFG1                    (0x4)
#define HI_2952_PHY_CFG0                    (0x100)
#define HI_2952_ANA_CFG5                    (0x14)
#define HI_2952_CKDT_STS                    (0x314)

#define HI_2952_USB2_PHY_BASE               (0x1193a000)
#define HI_2952_USB3_PHY_BASE               (0x11912000)

#define HI_2952_USB2_CLK_MASK               (0x7b)
#define HI_2952_USB3_CLK_MASK               (0xfab)
#define HI_2952_USB3_PHY_CLK_MASK           (0x3)
#define HI_2952_USB3_PHY_RST_MASK           (0x7)
#define HI_2952_USB2_RST_MASK               (0x5f)
#define HI_2952_USB3_RST_MASK               (0x28f)

#define HI_2952_REG_ACP                     (0x10113180)
#define HI_2952_USB3_CTRL_CTRL2             (0x11910c08)
#define HI_2952_USB2_CACHE_CTRL             (0x10113344)
#define HI_2952_USB3_XM_ARCACHE_SEL         (1 << 21)
#define HI_2952_USB3_XM_ARCACHE             ((0xffffffff >> (32 - (4))) << 16)
#define HI_2952_USB3_XM_AWCACHE_SEL         (1 << 12)
#define HI_2952_USB3_XM_AWCACHE             ((0xffffffff >> (32 - (4))) << 8)
#define HI_2952_USB2_XM_ARCACHE             ((0xffffffff >> (32 - (4))) << 20)
#define HI_2952_USB2_XM_AWCACHE             ((0xffffffff >> (32 - (4))) << 16)

#define USB_PHY_ADDR(base, reg)             (((base) + (reg)))

static struct hi_usb_ctrl_5115_reg_s g_usb_5115_reg_ctrl;
static struct hi_usb_ctrl_5116_reg_s g_usb_5116_reg_ctrl;
static struct hi_usb_ctrl_5118_reg_s g_usb_5118_reg_ctrl;
static struct hi_usb_ctrl_5610_reg_s g_usb_5610_reg_ctrl;
static struct hi_usb_ctrl_reg_s  g_usb_reg_ctrl;

static atomic_t dev_open_cnt = {
	.counter = 0,
};

static bool g_usb_acp_enable;
module_param_named(acp, g_usb_acp_enable, bool, 0444);
MODULE_PARM_DESC(acp, "USB ACP Enable");

static bool g_usb_xhci_gen2_force;
module_param_named(xhci_gen2, g_usb_xhci_gen2_force, bool, 0444);
MODULE_PARM_DESC(xhci_gen2, "USB XHCI Gen2 Speed Force Enable");

bool hiusb_acp_is_enabled(void)
{
	return g_usb_acp_enable;
}
EXPORT_SYMBOL(hiusb_acp_is_enabled);

static inline void hiusb_io_write(uint32_t addr, uint32_t val)
{
	void *reg_addr;

	reg_addr = ioremap(addr, sizeof(uint32_t));
	writel(val, reg_addr);
	iounmap(reg_addr);
}

static inline uint32_t hiusb_io_read(uint32_t addr)
{
	uint32_t val;
	void *reg_addr;

	reg_addr = ioremap(addr, sizeof(uint32_t));
	val = readl(reg_addr);
	iounmap(reg_addr);
	return val;
}

static inline void hiusb_io_reg_val_set(uint32_t addr, uint32_t mask, uint32_t val)
{
	void *reg_addr;
	uint32_t reg_val;
	unsigned long flags;

	reg_addr = ioremap(addr, sizeof(uint32_t));
	local_irq_save(flags);
	reg_val = readl(reg_addr);
	reg_val &= ~mask;
	reg_val |= val;
	local_irq_restore(flags);

	iounmap(reg_addr);
}

static inline void hiusb_io_reg_bit_set(uint32_t addr, uint32_t mask)
{
	void *reg_addr;
	uint32_t reg_val;
	unsigned long flags;

	reg_addr = ioremap(addr, sizeof(uint32_t));
	local_irq_save(flags);
	reg_val = readl(reg_addr);
	reg_val |= mask;
	local_irq_restore(flags);

	iounmap(reg_addr);
}

static inline void hiusb_io_reg_bit_clr(uint32_t addr, uint32_t mask)
{
	void *reg_addr;
	uint32_t reg_val;
	unsigned long flags;

	reg_addr = ioremap(addr, sizeof(uint32_t));
	local_irq_save(flags);
	reg_val = readl(reg_addr);
	reg_val &= ~mask;
	local_irq_restore(flags);

	iounmap(reg_addr);
}

static unsigned int hiusb_phy_cr_addr_cap(void __iomem *usb_misc_base_addr,
	unsigned int port, unsigned int waddr)
{
	unsigned int *usb3_reg_phy_ctrl;
	unsigned int *usb3_reg_phy_state;
	unsigned int val;

	usb3_reg_phy_ctrl = usb_misc_base_addr + 0x14 + 0x8 * port;
	usb3_reg_phy_state = usb_misc_base_addr + 0x60 + 0x4 * port;

	/* CRDATAIN = waddr, CRPADDR = 1 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRDATAIN;
	val |= ((waddr << 16) & USB3_MISC_CTRL_PHY_CRDATAIN);
	val |= USB3_MISC_CTRL_PHY_CRPADDR;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 1 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (!(val & USB3_MISC_STAT_PHY_CRACK)) {
		pr_err("config addr ack error!\n");
		return 1;
	}

	/* CRPADDR = 0 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRPADDR;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 0 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (val & USB3_MISC_STAT_PHY_CRACK) {
		pr_err("\nconfig addr check [ack = 0] fail!\n");
		return 1;
	}

	return 0;
}

static unsigned int hiusb_phy_cr_read(void __iomem *usb_misc_base_addr,
	unsigned int port, unsigned int *rdata)
{
	unsigned int *usb3_reg_phy_ctrl;
	unsigned int *usb3_reg_phy_state;
	unsigned int val;

	usb3_reg_phy_ctrl = usb_misc_base_addr + 0x14 + 0x8 * port;
	usb3_reg_phy_state = usb_misc_base_addr + 0x60 + 0x4 * port;

	/* CRREAD = 1 */
	val = readl(usb3_reg_phy_ctrl);
	val |= USB3_MISC_CTRL_PHY_CRREAD;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 1 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (!(val & USB3_MISC_STAT_PHY_CRACK)) {
		pr_err("config read data ack error!\n");
		return 1;
	}

	/* read data */
	val = readl(usb3_reg_phy_state);
	*rdata = val & USB3_MISC_STAT_PHY_CRDATAOUT;

	/* CRREAD = 0 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRREAD;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 0 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (val & USB3_MISC_STAT_PHY_CRACK) {
		pr_err("config read data check [ack = 0] fail!\n");
		return 1;
	}

	return 0;
}

static unsigned int hiusb_phy_cr_write(void __iomem *usb_misc_base_addr,
	unsigned int port, unsigned int wdata)
{
	unsigned int *usb3_reg_phy_ctrl;
	unsigned int *usb3_reg_phy_state;
	unsigned int val;

	usb3_reg_phy_ctrl = usb_misc_base_addr + 0x14 + 0x8 * port;
	usb3_reg_phy_state = usb_misc_base_addr + 0x60 + 0x4 * port;

	/* CRDATAIN = wdata, CRCAPDATA = 1 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRDATAIN;
	val |= ((wdata << 16) & USB3_MISC_CTRL_PHY_CRDATAIN);
	val |= USB3_MISC_CTRL_PHY_CRCAPDATA;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 1 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (!(val & USB3_MISC_STAT_PHY_CRACK)) {
		pr_err("write data check ack error!\n");
		return 1;
	}

	/* CRCAPDATA = 0 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRCAPDATA;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 0 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (val & USB3_MISC_STAT_PHY_CRACK) {
		pr_err("write data check [ack = 0] fail!\n");
		return 1;
	}

	/* CRWRITE = 1 */
	val = readl(usb3_reg_phy_ctrl);
	val |= USB3_MISC_CTRL_PHY_CRWRITE;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 1 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (!(val & USB3_MISC_STAT_PHY_CRACK)) {
		pr_err("write operation check ack error!\n");
		return 1;
	}

	/* CRWRITE = 0 */
	val = readl(usb3_reg_phy_ctrl);
	val &= ~USB3_MISC_CTRL_PHY_CRWRITE;
	writel(val, usb3_reg_phy_ctrl);

	/* wait CRACK = 0 */
	udelay(10);
	val = readl(usb3_reg_phy_state);
	if (val & USB3_MISC_STAT_PHY_CRACK) {
		pr_err("write operation check [ack = 0] fail!\n");
		return 1;
	}

	return 0;
}

static unsigned int hiusb_phy_write(void __iomem *usb_misc_base_addr,
	unsigned int port, unsigned int waddr, unsigned int wdata)
{
	unsigned int ret;

	ret = 0;
	ret |= hiusb_phy_cr_addr_cap(usb_misc_base_addr, port, waddr);
	ret |= hiusb_phy_cr_write(usb_misc_base_addr, port, wdata);
	return ret;
}

static unsigned int hiusb_phy_read(void __iomem *usb_misc_base_addr,
	unsigned int port, unsigned int raddr, unsigned int *rdata)
{
	unsigned int ret;

	ret = 0;
	ret |= hiusb_phy_cr_addr_cap(usb_misc_base_addr, port, raddr);
	ret |= hiusb_phy_cr_read(usb_misc_base_addr, port, rdata);
	return ret;
}

static void hiusb_5610_unmap_reg(void)
{
	iounmap(g_usb_5610_reg_ctrl.pv_peren0);
	iounmap(g_usb_5610_reg_ctrl.pv_perdis0);
	iounmap(g_usb_5610_reg_ctrl.pv_peren1);
	iounmap(g_usb_5610_reg_ctrl.pv_perdis1);
	iounmap(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	iounmap(g_usb_5610_reg_ctrl.pv_gusb3pipectrl0);
	iounmap(g_usb_5610_reg_ctrl.pv_gusb3pipectrl1);
}

static unsigned int hi_usb_5610_map_reg(void)
{
	g_usb_5610_reg_ctrl.pv_peren0 = ioremap(HI_SC_PEREN0, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_peren0 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_peren0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_perdis0 = ioremap(HI_SC_PERDIS0, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_perdis0 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_perdis0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_peren1 = ioremap(HI_SC_PEREN1, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_peren1 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_peren1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_perdis1 = ioremap(HI_SC_PERDIS1, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_perdis1 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_perdis1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_rst_ctrl0 = ioremap(HI_SC_RST_CTRL0, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_rst_ctrl0 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_rst_ctrl0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_gusb3pipectrl0 = ioremap(HI_GUSB3PIPECTL0, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_gusb3pipectrl0 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_gusb3pipectrl0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5610_reg_ctrl.pv_gusb3pipectrl1 = ioremap(HI_GUSB3PIPECTL1, sizeof(unsigned int));
	if (g_usb_5610_reg_ctrl.pv_gusb3pipectrl1 == NULL) {
		pr_err("ioremap error: g_usb_5610_reg_ctrl.pv_gusb3pipectrl1 = NULL\n");
		goto ioremap_fail_out;
	}
	return 0;
ioremap_fail_out:
	(void)hiusb_5610_unmap_reg();
	return -1;
}

static void hi_usb_5610T_start_hcd(void)
{
	unsigned int ui_val = 0;
	unsigned long flags;

	local_irq_save(flags);
	ui_val = readl(g_usb_5610_reg_ctrl.pv_peren0);
	ui_val |= 0x10c00;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_peren0);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_peren1);
	ui_val |= 1 << 22;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_peren1);

	udelay(10);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	ui_val &= 0xFFF07FFF;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_rst_ctrl0);

	udelay(20);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	ui_val |= 0xC0000;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_rst_ctrl0);

	udelay(250);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	ui_val |= 0x30000;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_rst_ctrl0);

	udelay(10);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	ui_val |= 0x8000;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_rst_ctrl0);

	udelay(10);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_gusb3pipectrl0);
	ui_val &= ~0x00020000;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_gusb3pipectrl0);

	udelay(10);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_gusb3pipectrl1);
	ui_val &= ~0x00020000;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_gusb3pipectrl1);

	local_irq_restore(flags);
}

static void hi_usb_5610T_stop_hcd(void)
{
	unsigned int ui_val;
	unsigned long flags;

	local_irq_save(flags);
	ui_val = 0;
	ui_val = readl(g_usb_5610_reg_ctrl.pv_rst_ctrl0);
	ui_val &= 0xFFF07FFF;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_rst_ctrl0);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_peren0);
	ui_val &= 0xFFFEF3FF;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_peren0);

	ui_val = readl(g_usb_5610_reg_ctrl.pv_peren1);
	ui_val &= 0xFFBFFFFF;
	writel(ui_val, g_usb_5610_reg_ctrl.pv_peren1);

	local_irq_restore(flags);
	hiusb_5610_unmap_reg();
}

static void hiusb_5115_unmap_reg(void)
{
	iounmap(g_usb_5115_reg_ctrl.IOMUX_SETL0);
	iounmap(g_usb_5115_reg_ctrl.PERI_PEREN);
	iounmap(g_usb_5115_reg_ctrl.PERI_PEREN1);
	iounmap(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	iounmap(g_usb_5115_reg_ctrl.PERI_PERCTRL39);
	iounmap(g_usb_5115_reg_ctrl.GPIO1_CTL);
	iounmap(g_usb_5115_reg_ctrl.GPIO2_CTL);
	iounmap(g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0);
	iounmap(g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1);
}

void hiusb_start_hcd_5115(void)
{
	unsigned int reg;
	unsigned long flags;

	g_usb_5115_reg_ctrl.IOMUX_SETL0 = ioremap(IOMUX_SEL0_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.IOMUX_SETL0 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.IOMUX_SETL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.PERI_PEREN = ioremap(PERI_PEREN_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.PERI_PEREN == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.PERI_PEREN = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.PERI_PEREN1 = ioremap(PERI_PEREN1_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.PERI_PEREN1 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.PERI_PEREN1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.PERI_PERCTRL36 = ioremap(PERI_PERCTRL36_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.PERI_PERCTRL36 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.PERI_PERCTRL36 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.PERI_PERCTRL39 = ioremap(PERI_PERCTRL39_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.PERI_PERCTRL39 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.PERI_PERCTRL39 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.GPIO1_CTL = ioremap(GPIO1_CTL_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.GPIO1_CTL == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.GPIO1_CTL = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.GPIO2_CTL = ioremap(GPIO2_CTL_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.GPIO2_CTL == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.GPIO2_CTL = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0 = ioremap(IOMUX_SEL_PHY0_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1 = ioremap(IOMUX_SEL_PHY1_ADDR, sizeof(unsigned int));
	if (g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1 == NULL) {
		pr_err("ioremap error: g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1 = NULL\n");
		goto ioremap_fail_out;
	}

	local_irq_save(flags);
	reg = readl(g_usb_5115_reg_ctrl.PERI_PEREN);
	reg |= USB_HCLK_EN;
	writel(USB_HCLK_EN, g_usb_5115_reg_ctrl.PERI_PEREN);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PEREN1);
	reg |= USB_CLK_EN;
	writel(USB_CLK_EN, g_usb_5115_reg_ctrl.PERI_PEREN1);

	udelay(100);

	/* enable all usb reset */
	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg &= ~USB_PORT1_RST;
	reg &= ~USB_PORT0_RST;
	reg &= ~USB_CTRL_RST;
	reg &= ~USB_SRST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL39);
	reg &= ~USB_PHY1_RST;
	reg &= ~USB_PHY0_RST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL39);

	udelay(100);

	/* disable usb phy reset */
	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg |= USB_SRST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL36);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL39);
	reg |= USB_PHY1_RST;
	reg |= USB_PHY0_RST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL39);

	udelay(200);

	/* disable usb controller reset */
	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg |= USB_PORT1_RST;
	reg |= USB_PORT0_RST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL36);

	udelay(100);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg |= USB_CTRL_RST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL36);

	udelay(100);

	/*configure for the reg of USB0 PHY */
	reg = readl(g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0);
	reg = 0x0a1d19dc;
	writel(reg, g_usb_5115_reg_ctrl.IOMUX_SEL_PHY0);

	/*configure for the reg of USB1 PHY */
	reg = readl(g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1);
	reg = 0x001d19dc;
	writel(reg, g_usb_5115_reg_ctrl.IOMUX_SEL_PHY1);

	local_irq_restore(flags);
	pr_info("hiusb_start_hcd successful(5115)!\n");
	if (0) {
ioremap_fail_out:
		hiusb_5115_unmap_reg();
	}
}

static void hiusb_5116_unmap_reg(void)
{
	iounmap(g_usb_5116_reg_ctrl.SC_PERCTRL38);
	iounmap(g_usb_5116_reg_ctrl.SC_PEREN1);
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	iounmap(g_usb_5116_reg_ctrl.IO_SEL0);
}

void hiusb_start_hcd_5116(void)
{
	enum HW_CHIP_ID_E hw_chip_id;
	int retval;

	hw_chip_id = get_chip_id_ont();

	g_usb_5116_reg_ctrl.SC_PERCTRL38 = ioremap(0x10100134, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_PERCTRL38 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_PERCTRL38 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_PEREN1 = ioremap(0x14880020, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_PEREN1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_PEREN1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_RST_CTRL0 = ioremap(0x1488002c, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_RST_CTRL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.IO_SEL0 = ioremap(0x14900200, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.IO_SEL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.IO_SEL0 = NULL\n");
		goto ioremap_fail_out;
	}

	if (hw_chip_id == HW_CHIP_ID_5116H_E) {
		retval = hiusb_start_hcd_5116H(&g_usb_5116_reg_ctrl);
		if (retval != 0)
			return;
	} else if ((hw_chip_id == HW_CHIP_ID_5116T_E) || (hw_chip_id == HW_CHIP_ID_5116TV5_E)) {
		retval = hiusb_start_hcd_5116T(&g_usb_5116_reg_ctrl);
		if (retval != 0)
			return;
	}
	pr_info("hiusb_start_hcd successful(5116)!\n");
	if (0) {
ioremap_fail_out:
		hiusb_5116_unmap_reg();
	}
}

static void hiusb_5118_unmap_reg(void)
{
	iounmap(g_usb_5118_reg_ctrl.SC_PER_CLK_EN1);
	iounmap(g_usb_5118_reg_ctrl.SC_PER_CLK_DIS1);
	iounmap(g_usb_5118_reg_ctrl.SC_PER_CLK_ST1);
	iounmap(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	iounmap(g_usb_5118_reg_ctrl.SC_PERCTRL62);
	iounmap(g_usb_5118_reg_ctrl.SC_PERCTRL66);
	iounmap(g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN0);
	iounmap(g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN1);
	iounmap(g_usb_5118_reg_ctrl.SC_PERI_USB3_GCTL);
}

void hiusb_start_hcd_5118(void)
{
	unsigned int reg;
	unsigned int *pui_reg = NULL;
	unsigned long flags;

	// remap usb controller clock enable reg
	g_usb_5118_reg_ctrl.SC_PER_CLK_EN1 = ioremap(0x14880020, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PER_CLK_EN1 == NULL) {
		pr_err("ioremap error: g_usb_5118_reg_ctrl.SC_PER_CLK_EN1 = NULL\n");
		goto ioremap_fail_out;
	}

	// remap usb controller clock enable reg
	g_usb_5118_reg_ctrl.SC_PER_CLK_DIS1 = ioremap(0x14880024, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PER_CLK_DIS1 == NULL) {
		pr_err("ioremap error: g_usb_5118_reg_ctrl.SC_PER_CLK_DIS1 = NULL\n");
		goto ioremap_fail_out;
	}

	// remap usb controller clock state reg
	g_usb_5118_reg_ctrl.SC_PER_CLK_ST1 = ioremap(0x14880028, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PER_CLK_ST1 == NULL) {
		pr_err("ioremap error: g_usb_5118_reg_ctrl.SC_PER_CLK_ST1 = NULL\n");
		goto ioremap_fail_out;
	}

	// remap usb phy and port reset reg
	g_usb_5118_reg_ctrl.SC_RST_CTRL0 = ioremap(0x1488002c, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_RST_CTRL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5118_reg_ctrl.SC_PERCTRL62 = ioremap(0x101001b0, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PERCTRL62 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5118_reg_ctrl.SC_PERCTRL66 = ioremap(0x101001c0, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PERCTRL66 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}
	g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN0 = ioremap(0x10a5c2c0, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}
	g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN1 = ioremap(0x10a5c2c4, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}
	g_usb_5118_reg_ctrl.SC_PERI_USB3_GCTL = ioremap(0x10a5c110, sizeof(unsigned int));
	if (g_usb_5118_reg_ctrl.SC_PERI_USB3_GCTL == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	// repair Teclast and Toshiba USB flash disk read reset error
	pui_reg = (unsigned int *)ioremap(0x10a5c10c, sizeof(unsigned int));
	if (pui_reg == NULL) {
		pr_err("ioremap error: 0x10a5c10c remap NULL!");
		goto ioremap_fail_out;
	}

	local_irq_save(flags);

	/* modify depends on hardware eye pattern */
	writel(0x1d96f005, g_usb_5118_reg_ctrl.SC_PERCTRL62);
	writel(0x1d96f005, g_usb_5118_reg_ctrl.SC_PERCTRL66);
	mdelay(1);

	// read clock state reg
	reg = readl(g_usb_5118_reg_ctrl.SC_PER_CLK_ST1);
	BIT_SET(reg, 0x1<<12);  // open usb controller clock
	BIT_SET(reg, 0x1<<16);  // open usb port0 usb2 reference clock
	BIT_SET(reg, 0x1<<17);  // open usb port1 usb2 reference clock
	BIT_SET(reg, 0x1<<18);  // open usb port0 usb3 reference clock
	BIT_SET(reg, 0x1<<19);  // open usb port1 usb3 reference clock
	writel(reg, g_usb_5118_reg_ctrl.SC_PER_CLK_EN1);

	// usb2 phy unreset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<15);  // port0 usb2 phy unreset
	BIT_SET(reg, 0x1<<12);  // port1 usb2 phy unreset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	udelay(40);    // logic suggest 35us

	// usb2 phy port unreset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<16);  // port0 usb2 port unreset
	BIT_SET(reg, 0x1<<13);  // port1 usb2 port unreset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	// usb3 phy unreset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<28);  // port0 usb3 phy unreset
	BIT_SET(reg, 0x1<<30);  // port1 usb3 phy unreset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	udelay(15);    // logic suggest 10us

	// usb3 phy port unreset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<29);  // port0 usb3 port unreset
	BIT_SET(reg, 0x1<<31);  // port1 usb3 port unreset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	udelay(15);    // logic suggest 10us

	// usb controller unreset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<14);  // usb controller unreset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	udelay(5);    // logic suggest 1us
	// synopsys T28HPM COMBO PHY work mode is USB SS, not support rx_detect
	// Disabled receiver detection in P3 (DisRxDetP3)
	// write 0x1, addr 0x10A5_C2C4 write 0x110E_0002
	reg = readl(g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN0);
	BIT_SET(reg, 0x1<<28);  // Disabled receiver detection in P3 (DisRxDetP3)
	writel(reg, g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN0);

	reg = readl(g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN1);
	BIT_SET(reg, 0x1<<28);  // Disabled receiver detection in P3 (DisRxDetP3)
	writel(reg, g_usb_5118_reg_ctrl.SC_PERI_PHYCFGN1);

	// Power Down Scale (PwrDnScale) write 0x3f, addr 0x10A5_C110 write 0x1f81004
	reg = readl(g_usb_5118_reg_ctrl.SC_PERI_USB3_GCTL);
	BIT_CLR(reg, 0x1fff << 19);
	BIT_SET(reg, 0x3f << 19);  // Power Down Scale
	writel(reg, g_usb_5118_reg_ctrl.SC_PERI_USB3_GCTL);

	udelay(5);  // logic suggest 1us

	reg = (readl(pui_reg) & (~0x2ff80000));
	reg |= 0x21080000;
	writel(reg, pui_reg);

	local_irq_restore(flags);
	iounmap(pui_reg);

	pr_info("hiusb_start_hcd successful(5118)!\n");
	if (0) {
ioremap_fail_out:
		hiusb_5118_unmap_reg();
	}
}

void hiusb_start_hcd_5117h(void)
{
	unsigned int reg;
	unsigned long flags;
	// usb controller reg remap
	g_usb_reg_ctrl.clk_open = ioremap(0x14880020, sizeof(unsigned int));
	g_usb_reg_ctrl.clk_close = ioremap(0x14880024, sizeof(unsigned int));
	g_usb_reg_ctrl.reset = ioremap(0x1488002c, sizeof(unsigned int));
	g_usb_reg_ctrl.func_sel = ioremap(0x14900120, sizeof(unsigned int));
	g_usb_reg_ctrl.phy_cfg = ioremap(0x10100154, sizeof(unsigned int));

	if (!g_usb_reg_ctrl.clk_open || !g_usb_reg_ctrl.clk_close ||
		!g_usb_reg_ctrl.reset || !g_usb_reg_ctrl.func_sel || !g_usb_reg_ctrl.phy_cfg) {
		if (g_usb_reg_ctrl.clk_open)
			iounmap(g_usb_reg_ctrl.clk_open);
		if (g_usb_reg_ctrl.clk_close)
			iounmap(g_usb_reg_ctrl.clk_close);
		if (g_usb_reg_ctrl.reset)
			iounmap(g_usb_reg_ctrl.reset);
		if (g_usb_reg_ctrl.func_sel)
			iounmap(g_usb_reg_ctrl.func_sel);
		if (g_usb_reg_ctrl.phy_cfg)
			iounmap(g_usb_reg_ctrl.phy_cfg);
		pr_err("ioremap error\n");
		return;
	}

	local_irq_save(flags);

	// enable usb over cur(gpio29) and poweren pin(gpio30), 0x14900120[29]=1
	reg = readl(g_usb_reg_ctrl.func_sel);
	reg |= (1UL << 29);
	writel(reg, g_usb_reg_ctrl.func_sel);

	// open usb controller clock, 0x14880020[12]=1
	writel((1UL << 12), g_usb_reg_ctrl.clk_open);

	// unreset usb phy, 0x1488002c[15]=1
	reg = readl(g_usb_reg_ctrl.reset);
	reg |= (1UL << 15);
	writel(reg, g_usb_reg_ctrl.reset);

	mdelay(1);    // wait 1ms until usbphy output stable

	// unreset usb port, 0x1488002c[16]=1
	reg = readl(g_usb_reg_ctrl.reset);
	reg |= (1UL << 16);
	writel(reg, g_usb_reg_ctrl.reset);

	// unreset usb controller, 0x1488002c[14]=1
	reg = readl(g_usb_reg_ctrl.reset);
	reg |= (1UL << 14);
	writel(reg, g_usb_reg_ctrl.reset);

	// disconnect threshold config
	for (reg = 0; reg < 4; reg++) {
		writel(0xc003111, g_usb_reg_ctrl.phy_cfg);
		writel(0xc003110, g_usb_reg_ctrl.phy_cfg);
	}

	local_irq_restore(flags);
	pr_info("hiusb_start_hcd successful(5117h)!\n");
}

// init hiusb for 5117p
void hiusb_start_hcd_hwsoc1(void)
{
	unsigned int val;
	void __iomem *pv_iomux_base_virt;
	void __iomem *pv_crg_base_virt;
	void __iomem *pv_usb_misc_base_virt;
	unsigned long flags;

	// usb controller reg remap
	pv_crg_base_virt = ioremap(0x148a0000, 0x300);
	if (!pv_crg_base_virt) {
		pr_err("Cannot map crg register base!");
		return;
	}

	pv_iomux_base_virt = ioremap(0x14900000, 0x1000);
	if (!pv_iomux_base_virt) {
		pr_err("Cannot map iomux register base!");
		iounmap(pv_crg_base_virt);
		return;
	}

	pv_usb_misc_base_virt = ioremap(0x10168000, 0x100);
	if (!pv_usb_misc_base_virt) {
		pr_err("Cannot map gpio register base!");
		iounmap(pv_crg_base_virt);
		iounmap(pv_iomux_base_virt);
		return;
	}

	local_irq_save(flags);
	// open usb2 controller clock, 0x148a0020[12]=1
	writel(1UL << 12, pv_crg_base_virt + 0x20);

	// unreset usb2 phy, 0x148a002c[12]=1
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL << 12);
	writel(val, pv_crg_base_virt + 0x2c);

	mdelay(1);    // wait 1ms until usbphy output stable

	// unreset usb2 port, 0x148a002c[13]=1
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL << 13);
	writel(val, pv_crg_base_virt + 0x2c);

	// unreset usb controller, 0x148a0030[17]=1
	val = readl(pv_crg_base_virt + 0x30);
	val = val | (1UL << 17);
	writel(val, pv_crg_base_virt + 0x30);

	/* unreset usb controller MISC, 0x148a01ac, bit[0]=1 port0, soft reset USB APB bus */
	val = readl(pv_crg_base_virt + 0x01ac);
	val = val | (1UL << 0);
	writel(val, pv_crg_base_virt + 0x01ac);

	// usb3 vbus config
	val = readl(pv_usb_misc_base_virt + 0x0);
	val = val & (~0x54);
	writel(val, pv_usb_misc_base_virt + 0x0);

	// usb3 phy config
	writel(0x00025F33, pv_usb_misc_base_virt + 0x4);
	writel(0x0680CA4C, pv_usb_misc_base_virt + 0x10);
	writel(0x0680CA4C, pv_usb_misc_base_virt + 0x18);

	// open usb3 apb clock
	writel(1UL<<31, pv_crg_base_virt + 0x20);

	// open usb3 controller clock
	writel(1UL<<30, pv_crg_base_virt + 0x20);

	// open usb3 phy clock
	writel(1UL<<18, pv_crg_base_virt + 0x20);

	// open usb2 phy clock
	writel(1UL<<16, pv_crg_base_virt + 0x20);

	// unreset usb2 phy
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL<<15);
	writel(val, pv_crg_base_virt + 0x2c);
	udelay(40);
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL<<16);
	writel(val, pv_crg_base_virt + 0x2c);

	// unreset usb3 phy
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL<<28);
	writel(val, pv_crg_base_virt + 0x2c);
	udelay(15);
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL<<29);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(15);
	// unreset usb controller
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (1UL<<14);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(5);

	if (hiusb_acp_is_enabled()) {
		/* PERI_USB3_GTXTHRCFG configuration to increase the USB speed in acp mode
		 * usbtxpktcntsel=1 USB TXFIFO threshold select 1: The USB transmits data only
		 * after the specified packet is read to the specified TX FIFO
		 * usbtxpktcnt=3 TXFIFO threshold setting
		 * usbmaxtxburstsize=8 maximum number of bursts to be sent
		 */
		hiusb_io_write(0x1060c108, 0x23080000);
	}

	hiusb_phy_read(pv_usb_misc_base_virt, 0, 0x102b, &val);
	val &= ~(0x1 << 2);
	val |= (0x1 << 3);
	val |= (0x1 << 4);
	hiusb_phy_write(pv_usb_misc_base_virt, 0, 0x102b, val);

	local_irq_restore(flags);
	iounmap(pv_crg_base_virt);
	iounmap(pv_iomux_base_virt);
	iounmap(pv_usb_misc_base_virt);
	pr_info("hiusb_start_hcd successful(hwsoc1)!\n");
}

// init hiusb for 5117v
void hiusb_start_hcd_hwsoc3(void)
{
	unsigned int reg;
	unsigned int val;
	unsigned int *pui_reg = NULL;

	void __iomem *pv_crg_base_virt;
	void __iomem *pv_usb_misc_base_virt;
	void __iomem *pv_tzpc_base_virt;
	unsigned long flags;

	// usb controller reg remap
	pv_crg_base_virt = ioremap(0x148a0000, 0x300);
	if (!pv_crg_base_virt) {
		pr_err("Cannot map crg register base!");
		return;
	}

	pv_usb_misc_base_virt = ioremap(0x10168000, 0x1000);
	if (!pv_usb_misc_base_virt) {
		pr_err("Cannot map usb_misc register base!");
		iounmap(pv_crg_base_virt);
		return;
	}

	/* security feature of the 17v is added. You need to set the USB port
	 * to the security mode. You only need to configure the master machine
	 */
	pv_tzpc_base_virt = ioremap(ECS_TZPC_BASE, 0x1000);
	if (!pv_tzpc_base_virt) {
		pr_err("Cannot map tzpc register base!");
		iounmap(pv_crg_base_virt);
		iounmap(pv_usb_misc_base_virt);
		return;
	}

	// repair tai dian and dong zhi Upan read reset error
	pui_reg = (unsigned int *)ioremap(0x1060c10c, sizeof(unsigned int));
	if (pui_reg == NULL) {
		pr_err("ioremap 0x0c10c error!\n");
		iounmap(pv_crg_base_virt);
		iounmap(pv_usb_misc_base_virt);
		iounmap(pv_tzpc_base_virt);
		return;
	}

	local_irq_save(flags);
	/* 'TZPC_MST 0x10100008 usb3_mst_prot_cfg bit[3]=0 */
	val = readl(pv_tzpc_base_virt + 0x8);
	val = val & (~(1UL << 3));
	writel(val, pv_tzpc_base_virt + 0x8);

	iounmap(pv_tzpc_base_virt);

	/* End of USB security configuration for the 17v chip. */

	/* Configure the USB clock, PHY, and reset and deassert
	 * reset by referring to the user guide and 17p chip.
	 */

	/* open usb2 usb3 phy clock:0x148a0020 bit[16:19]=1*/
	val = readl(pv_crg_base_virt + 0x20);
	val = val | (0xf << 16);
	writel(val, pv_crg_base_virt + 0x20);

	/* open usb2 usb3 controller clock:0x148a0020 bit[30:31]=1*/
	val = readl(pv_crg_base_virt + 0x20);
	val = val | (0x3 << 30);
	writel(val, pv_crg_base_virt + 0x20);

	/* unreset usb controller MISC 0x148a01ac bit[0]=1*/
	val = readl(pv_crg_base_virt + 0x1AC);
	val = val | (0x1 << 0);
	writel(val, pv_crg_base_virt + 0x1AC);

	/* unreset usb2 phy 0x148a002c
		port0_usb2_phy_srst_n:bit[15]=1  port1_usb2_phy_srst_n:bit[12]=1*/
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (0x1 << 12);
	val = val | (0x1 << 15);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(40);    // logic suggest 20us

	/* unreset usb2 port 0x148a002c
		port0_usb2_phy_port_srst_n:bit[16]=1  port1_usb2_phy_port_srst_n:bit[13]=1*/
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (0x1 << 13);
	val = val | (0x1 << 16);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(40);    // logic suggest 20us

	/* unreset usb3 phy 0x148a002c
		port0_usb3_phy_srst_n:bit[28]=1  port1_usb3_phy_srst_n:bit[30]=1*/
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (0x1 << 28);
	val = val | (0x1 << 30);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(40);    // logic suggest 20us

	/* unreset usb3 port 0x148a002c
		port0_usb3_phy_port_srst_n:bit[29]=1  port1_usb3_phy_port_srst_n:bit[13]=1*/
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (0x1 << 29);
	val = val | (0x1 << 31);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(40);    // logic suggest 20us

	/* unreset usb2 usb3 controller 0x148a002c port0_usb_srst_n:bit[14]=1*/
	val = readl(pv_crg_base_virt + 0x2c);
	val = val | (0x1 << 14);
	writel(val, pv_crg_base_virt + 0x2c);

	udelay(40);    // logic suggest 20us

	/* config done */

	/* comfirmed this modification need to be inherited.
	 * 17v and 17p are comfirmed to be same
	 */
	reg = (readl(pui_reg) & (~0x2FF80000));
	reg |= 0x21080000;
	writel(reg, pui_reg);

	local_irq_restore(flags);
	iounmap(pui_reg);
	iounmap(pv_crg_base_virt);
	iounmap(pv_usb_misc_base_virt);
	pr_info("hiusb_start_hcd successful(hwsoc3)!\n");
}

static void hiusb_hwsoc2_unmap_reg(void)
{
	iounmap(g_usb_5116_reg_ctrl.SC_PEREN1);
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL1);
	iounmap(g_usb_5116_reg_ctrl.IO_SEL0);
}

// init hiusb for 5117l
void hiusb_start_hcd_hwsoc2(void)
{
	unsigned int reg;
	unsigned long flags;

	pr_info("hiusb_start_hcd begin(hwsoc2)!\n");

	g_usb_5116_reg_ctrl.SC_PEREN1 = ioremap(0x14880020, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_PEREN1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_PEREN1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_RST_CTRL0 = ioremap(0x1488002c, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_RST_CTRL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_RST_CTRL1 = ioremap(0x10100154, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_RST_CTRL1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.IO_SEL0 = ioremap(0x14900140, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.IO_SEL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.IO_SEL0 = NULL\n");
		goto ioremap_fail_out;
	}

	local_irq_save(flags);
	/* USB2_PWREN and USB2_OVRCUR pins of the 17L correspond to GPIO 27 and GPIO 28 */
	reg = readl(g_usb_5116_reg_ctrl.IO_SEL0);  // io_mux pin mux
	reg |= 0x18000000;
	writel(reg, g_usb_5116_reg_ctrl.IO_SEL0);

	mdelay(2);

	/* 'SC_PEREN1 usb_clk_en 0x14880020 bit12*/
	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock enable
	reg |= 0x1000;
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);

	mdelay(2);

	/* 'SC_RST_CTRL0 usbphy_srst_n 0x1488002c bit15 */
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy reset release
	reg |= 0x8000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	/* 'SC_RST_CTRL0 usbphy_port_srst_n 0x1488002c bit16 */
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy port reset release
	reg |= 0x10000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	/* 'SC_RST_CTRL0 usb_srst_n 0x1488002c bit14 */
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset release
	reg |= 0x4000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	mdelay(2);

	/* comfirmed ohci need to inherite 16h config, otherwise, ohci is suspended */
	for (reg = 0; reg < 4; reg++) {  // disconnect threshold config
		writel(0xC003111, g_usb_5116_reg_ctrl.SC_RST_CTRL1);
		writel(0xC003110, g_usb_5116_reg_ctrl.SC_RST_CTRL1);
	}

	mdelay(2);

	local_irq_restore(flags);
	pr_info("hiusb_start_hcd successful(hwsoc2)!\n");
	if (0) {
ioremap_fail_out:
		hiusb_hwsoc2_unmap_reg();
	}
}

static void hiusb_hwsoc4_unmap_reg(void)
{
	hiusb_5116_unmap_reg();
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL1);
}

// for 5182
void hiusb_start_hcd_hwsoc4(void)
{
	unsigned int reg;
	void __iomem *pv_usb_misc_base_virt = 0;
	void __iomem *pv_periphctrl0 = NULL;
	void __iomem *pv_peri_usb3_grxthrcfg = NULL;
	unsigned long flags;

	/* 5182H */
	pr_info("hiusb_start_hcd begin(hwsoc4)!\n");
	/* resolve 82h usb issue, set all AR and AW to non-bypass */
	pv_periphctrl0 = ioremap(USB3_PERIPHCTRL0_ADDR, 0x10); /* map 0x10 addr */
	if (pv_periphctrl0 == NULL) {
		pr_err("Cannot map pv_periphctrl0!\n");
		return;
	}

	pv_peri_usb3_grxthrcfg = ioremap(USB3_PERI_GRXTHRCFG_ADDR, 0x10); /* map 0x10 addr */
	if (pv_peri_usb3_grxthrcfg == NULL) {
		pr_err("Cannot map pv_peri_usb3_grxthrcfg!\n");
		goto ioremap_fail_out;
	}

	pv_usb_misc_base_virt = ioremap(0x10168000, 0x1000);
	if (pv_usb_misc_base_virt == NULL) {
		pr_err("Cannot map usb_misc register base!");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_PEREN1 = ioremap(0x14880020, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_PEREN1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_PEREN1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_RST_CTRL0 = ioremap(0x14880034, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_RST_CTRL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.SC_RST_CTRL1 = ioremap(0x10100154, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.SC_RST_CTRL1 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.SC_RST_CTRL1 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.IO_SEL0 = ioremap(0x14900140, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.IO_SEL0 == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.IO_SEL0 = NULL\n");
		goto ioremap_fail_out;
	}

	g_usb_5116_reg_ctrl.FUNCTION_PIN_SEL = ioremap(0x1490014C, sizeof(unsigned int));
	if (g_usb_5116_reg_ctrl.FUNCTION_PIN_SEL == NULL) {
		pr_err("ioremap error: g_usb_5116_reg_ctrl.FUNCTION_PIN_SEL = NULL\n");
		goto ioremap_fail_out;
	}

	local_irq_save(flags);
	reg = readl(pv_periphctrl0);
	reg = reg & (~0x8010);/* bit4 bit15 set 0 */
	writel(reg, pv_periphctrl0);

	mdelay(2);

	/* 'SC_PEREN1 usb_ctrl_clk_gate_en    0x14880020 bit21~22 16~19*/
	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock enable
	BIT_SET(reg, 0x1<<21);  // open usb apb controller clock
	BIT_SET(reg, 0x1<<22);  // open usb controller clock
	BIT_SET(reg, 0x1<<16);  // open usb port0 usb2 reference clock
	BIT_SET(reg, 0x1<<17);  // open usb port1 usb2 reference clock
	BIT_SET(reg, 0x1<<18);  // open usb port0 usb3 reference clock
	BIT_SET(reg, 0x1<<19);  // open usb port1 usb3 reference clock
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);

	mdelay(2);

	// usb2 phy unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<24);  // port0 usb2 phy unreset
	BIT_SET(reg, 0x1<<28);  // port1 usb2 phy unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	// usb2 phy port unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<25);  // port0 usb2 port unreset
	BIT_SET(reg, 0x1<<29);  // port1 usb2 port unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	// usb3 phy unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<26);  // port0 usb3 phy unreset
	BIT_SET(reg, 0x1<<30);  // port1 usb3 phy unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	// usb3 phy port unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_SET(reg, 0x1<<27);  // port0 usb3 port unreset
	BIT_SET(reg, 0x1<<31);  // port1 usb3 port unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	/* 'SC_RST_CTRL0 apb_usb_srst_n usb_srst_n 0x14880034 bit22~23 */
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset release
	BIT_SET(reg, 0x1<<22);  // usb apb unreset
	BIT_SET(reg, 0x1<<23);  // usb controller unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	mdelay(2);

	if (hiusb_acp_is_enabled()) {
		/* PERI_USB3_GTXTHRCFG configuration to increase the USB speed in acp mode
		 * usbtxpktcntsel=1 USB TXFIFO threshold select 1: The USB transmits data only
		 * after the specified packet is read to the specified TX FIFO
		 * usbtxpktcnt=3 TXFIFO threshold setting
		 * usbmaxtxburstsize=8 maximum number of bursts to be sent
		 */
		hiusb_io_write(0x1060c108, 0x23080000);
	}

	/* USB 3.0 test shows that the default Rxeq configuration
	 * is not optimal. It is recommended that the Rxeq
	 * configuration be changed to 0xB80 to ensure that the
	 * USB 3.0 RX jitter tolerance test passes
	 *
	 * Configure RX_EQ by referring to the USB 3.0 SSPHY Reference Manual.
	 * RX_OVRD_IN_HI[6]       RX_EQ_EN = 0
	 * RX_OVRD_IN_HI[7]       RX_EQ_EN_OVRD = 1
	 * RX_OVRD_IN_HI[10:8]    RX_EQ = 0x3
	 * RX_OVRD_IN_HI[11]      RX_EQ_OVRD = 1
	 */
	hiusb_phy_read(pv_usb_misc_base_virt, 0, 0x1006, &reg);
	reg &= ~(0x3FUL << 6);
	reg |= (0x1 << 7);
	reg |= (0x3 << 8);
	reg |= (0x1 << 11);
	hiusb_phy_write(pv_usb_misc_base_virt, 0, 0x1006, reg);

	hiusb_phy_read(pv_usb_misc_base_virt, 1, 0x1006, &reg);
	reg &= ~(0x3FUL << 6);
	reg |= (0x1 << 7);
	reg |= (0x3 << 8);
	reg |= (0x1 << 11);
	hiusb_phy_write(pv_usb_misc_base_virt, 1, 0x1006, reg);

	/* Resolve the USB 3.0 identification failure caused by high common-mode voltage
	 * LANEN_ANA_TX_TXDRV_CNTRL bit2: unused. The default value is 1, and the value is 0
	 * bit3:ovrd_vcm_hold set to 1, the output level is vcm_hold_reg
	 * bit4：vcm_hold_reg
	 */
	hiusb_phy_read(pv_usb_misc_base_virt, 0, 0x102b, &reg);
	reg &= ~(0x1 << 2);
	reg |= (0x1 << 3);
	reg |= (0x1 << 4);
	hiusb_phy_write(pv_usb_misc_base_virt, 0, 0x102b, reg);

	hiusb_phy_read(pv_usb_misc_base_virt, 1, 0x102b, &reg);
	reg &= ~(0x1 << 2);
	reg |= (0x1 << 3);
	reg |= (0x1 << 4);
	hiusb_phy_write(pv_usb_misc_base_virt, 1, 0x102b, reg);

	/* RX FIFO watermark level needs to be adjusted to solve the 82H USB problem */
	reg = readl(pv_peri_usb3_grxthrcfg);
	reg = reg & (~0x2FF80000); /* clear the corresponding bit */
	reg = reg | (0x21080000);  /* set rxfifo watermark level */
	writel(reg, pv_peri_usb3_grxthrcfg);

	local_irq_restore(flags);
	iounmap(pv_usb_misc_base_virt);
	iounmap(pv_periphctrl0);
	iounmap(pv_peri_usb3_grxthrcfg);
	pr_info("hiusb_start_hcd successful(hwsoc4)!\n");
	if (0) {
ioremap_fail_out:
		hiusb_hwsoc4_unmap_reg();
		iounmap(pv_periphctrl0);
		iounmap(pv_usb_misc_base_virt);
		iounmap(pv_peri_usb3_grxthrcfg);
	}
}

void hiusb_utmi_phy_clk_20m_enable(uint32_t port)
{
	uint32_t phy_base = USB2_PHY_BASE_GET_82T(port);

	/* suspend pll bypass */
	hiusb_io_reg_bit_set(phy_base + USB2_PHY_ANA_CFG1, (0x1UL << 30));
	/* enable 20MHZ ref clock */
	hiusb_io_reg_val_set(phy_base + USB2_PHY_PHY_CRG0,
		((0x1UL << 9) | (0x1UL << 8)), (0x1UL << 8));
	/* rg_pll_en_cfg = 1 */
	hiusb_io_reg_bit_set(phy_base + USB2_PHY_ANA_CFG5, (0x1UL << 1));
	/* rg_pll_en_val = 1 */
	hiusb_io_reg_bit_set(phy_base + USB2_PHY_ANA_CFG5, (0x1UL << 0));
}

// fot 5182T
void hiusb_start_hcd_hwsoc8(void)
{
	uint32_t i;

	if (g_usb_acp_enable) {
		/* ACP enable */
		hiusb_io_reg_bit_clr(ACP_SUBSYS_CTRL_82T,
			ACP_SUBSYS_CTRL_82T_USB3_ACP_HIGH_ADDR_EN);
	} else {
		/* ACP disable, enabling DDR passthrough */
		hiusb_io_reg_bit_set(ACP_SUBSYS_CTRL_82T,
			ACP_SUBSYS_CTRL_82T_USB3_ACP_HIGH_ADDR_EN);
	}

	mdelay(2);

	/* 'SC_PEREN1 usb_ctrl_clk_gate_en    0x14880020 bit17~22 5~6 */
	if (g_usb_xhci_gen2_force) {
		hiusb_io_write(0x14880020, USB_CLK_ENABLE_82T_GEN2);
		hiusb_io_write(0x14880024, USB_CLK_EN_82T_GEN3_PHY);
	} else {
		hiusb_io_write(0x14880020, USB_CLK_ENABLE_82T);
	}
	mdelay(1);

	/* usb_pcie_phy_mode = 1(USB SS), 0(PCIE) */
	if (!g_usb_xhci_gen2_force)
		hiusb_io_write(0x1011C820, 1);

	/* usb2_p1/0_utmi_clk_src_sel = 0(60M_clk), 1(utmi_clk) */
	hiusb_io_reg_bit_clr(0x14880138, ((0x1UL << 10) | (0x1UL << 9)));

	/* usb apb unreset */
	hiusb_io_reg_bit_set(0x14880034, USB_APB_UNRESET_82T);

	/* enable utmi_phy_clk_20M of PHY0 and PHY1 */
	hiusb_utmi_phy_clk_20m_enable(0);
	hiusb_utmi_phy_clk_20m_enable(1);

	/* usb phy0 and phy1 clock enable */
	hiusb_io_reg_bit_set(0x148802D4, USB_PHY_CLK_ENABLE_82T);
	mdelay(1);

	/* usb phy and phy port unreset */
	if (g_usb_xhci_gen2_force) {
		hiusb_io_reg_bit_set(0x14880034, USB_PHY_POR_UNRESET_82T_GEN2);
		hiusb_io_reg_bit_clr(0x14880034, USB_PHY_POR_SRSTN_82T_GEN3);
		mdelay(1);
		hiusb_io_reg_bit_set(0x14880034, USB_PHY_PORT_UNRESET_82T_GEN2);
		hiusb_io_reg_bit_clr(0x14880034, USB_PHY_PORT_SRSTN_82T_GEN3);
		mdelay(1);
	} else {
		hiusb_io_reg_bit_set(0x14880034, USB_PHY_POR_UNRESET_82T);
		mdelay(1);
		hiusb_io_reg_bit_set(0x14880034, USB_PHY_PORT_UNRESET_82T);
		mdelay(1);
	}

	/* 'SC_RST_CTRL0 controller unreset */
	hiusb_io_reg_bit_set(0x14880034, (1 << 21));
	mdelay(1);

	if (g_usb_xhci_gen2_force)
		hiusb_io_reg_bit_set(0x10160000 + 0xC04, 0xF0);
	else
		hiusb_io_reg_bit_clr(0x10160000 + 0xC04, 0xF0);

	/* USB 2.0 PHY configuration, enabling half-bit
	 * HSTX de-emphasis to improve HS rate eye diagram
	 */
	for (i = 0; i < 2; i++) { /* 2 PHY */
		/* ANA_CFG2[27:20] rg_test_tx(TX TEST bit) = 0x2 */
		hiusb_io_reg_val_set(USB2_PHY_BASE_GET_82T(i) + USB2_PHY_ANA_CFG2,
			USB2_PHY_ANA_CFG2_RG_TEST_TX_MSK, 0x2 << USB2_PHY_ANA_CFG2_RG_TEST_TX_POS);

		/* ANA_CFG0[11:8] rg_hstx_de(HSTX DE-emphasis strength config) = 0x2
		 * ANA_CFG0[5]    rg_hstx_deen(HSTX DE-emphasis Enable) = 1
		 */
		hiusb_io_reg_bit_set(USB2_PHY_BASE_GET_82T(i) + USB2_PHY_ANA_CFG0,
			USB2_PHY_ANA_CFG0_RG_HSTX_DEEN);
		hiusb_io_reg_val_set(USB2_PHY_BASE_GET_82T(i) + USB2_PHY_ANA_CFG0,
			USB2_PHY_ANA_CFG0_RG_HSTX_DE_MSK, 0x2 << USB2_PHY_ANA_CFG0_RG_HSTX_DE_POS);

		/* ANA_CFG3 = 0x400_0000 */
		hiusb_io_write(USB2_PHY_BASE_GET_82T(i) + USB2_PHY_ANA_CFG3, 0x4000000);

		/* ANA_CFG4[6:4] rg_vtxref_sel = 0x5(410mv) */
		hiusb_io_reg_val_set(USB2_PHY_BASE_GET_82T(i) + USB2_PHY_ANA_CFG4,
			USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_MSK, USB2_PHY_ANA_CFG4_RG_VTXREF_SEL_410MV);
	}
}

void hiusb_start_hcd_soc12(void)
{
	unsigned long timeout = 0;

	/* usb2.0 host */
	/* usb2.0 clock on */
	hiusb_io_reg_bit_set(HI_1156_FST_N_GATE_EN_USB2_1, HI_1156_USB2_CLK_EN);
	udelay(1);

	/* usb2 controller apb dereset */
	hiusb_io_reg_bit_set(HI_1156_FST_N_SRST_USB2_1, (1 << 6));

	/* [2]usb2 phy por dereset, [0]usb2 phy apb dereset */
	hiusb_io_reg_bit_set(HI_1156_FST_N_SRST_USB2_1, (1 << 0) | (1 << 2));

	/* [30]rg_pll_bypass_suspendm set 1, [28]usb2 phy default crystal oscillator clock */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG1), (1 << 30));
	hiusb_io_reg_bit_clr(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG1), (1 << 28));

	/* [9:8]select 24MHz as reference clock frequency, 0x0 */
	hiusb_io_reg_val_set(HI_1156_USB2PHY_ADDR(FASTIO_N, PHY_CRG0), (1 << 8) | (1 << 9), 0x0);

	/* [1]rg_pll_en_cfg set 1, [0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG5), (1 << 0));

	/* [1]usb2phy_sys_com_srst_n dereset, [3]usb2phy1_port_srst_n dereset */
	hiusb_io_reg_bit_set(HI_1156_FST_N_SRST_USB2_1, (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_FST_N_SRST_USB2_1, (1 << 3));
	mdelay(3);

	/* Wait until the USB2 PHY output clock is stable */
	while ((hiusb_io_read(HI_1156_USB2PHY_ADDR(FASTIO_N, CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_err("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}
	/* [4]usb2 controller dereset */
	hiusb_io_reg_bit_set(HI_1156_FST_N_SRST_USB2_1, (1 << 4));

	/* usb3.0 host */
	/* [0]sc_usb2phy_utmi_clk_sel_fastio_s, 0: 60M clk, 1: utmi clk */
	hiusb_io_reg_bit_set(HI_1156_FST_S_FREQ_CTRL_USB, (1 << 0));
	/* usb clock on */
	hiusb_io_reg_bit_set(HI_1156_FST_S_GATE_EN_USB0, HI_1156_USB3_CLK_EN);
	/* upsphy clock on */
	hiusb_io_reg_bit_set(HI_1156_FST_S_GATE_EN_UPSPHY_0, HI_1156_USB3_UPSPHY_CLK_EN);
	udelay(1);

	/* [9]sc_srst_n_u3hst_apb
	 * [0]sc_srst_n_u2phy_apb_fastio_s
	 * usb apb dereset
	 */
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_USB0, (1 << 9) | (1 << 0));

	/* [2]sc_srst_n_usb2phy_por_fastio_s, usb2phy por, 1: dereset, 0: reset
	 */
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_USB0, (1 << 2));

	/* [27]xhc_bme, 0: bus master disable, 1: bus master enable */
	hiusb_io_reg_bit_set(HI_1156_USB3_CTRL_CTRL1, (1 << 27));
	/* [0]fst_s_misc_ups_phy_mode_0
	 * [1]fst_s_misc_ups_phy_mode_1
	 */
	hiusb_io_reg_val_set(HI_1156_FST_S_UPS_CTL0, (1 << 0) | (1 << 1), (1 << 0));
	/* [1:0]UPSPHY multiplexing mode. 0: PCIe; 1: 2.5GE or USB; 25 MHz reference clock
	 * [3]fst_s_misc_usb_clk_sel0
	 */
	hiusb_io_reg_bit_set(HI_1156_FST_S_UPS_CTL1, (1 << 0) | (1 << 3));
	/* [0]misc_fs_ups_phy_iso_enb */
	hiusb_io_reg_bit_set(HI_1156_FST_S_UPS_CTL2, (1 << 0));

	/* upsphy dereset */
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_UPSPHY_0, HI_1156_USB3_UPSPHY_RST);
	/* [30]rg_pll_bypass_suspendm */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG1), (1 << 30));
	/* [1]ck_usable_sel, clock usable source select, 1: PLL, 0: LOCK DET */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, PHY_CRG0), (1 << 1));
	/* [1]rg_pll_en_cfg set 1，[0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG5), (1 << 0));

	/* [1]sc_srst_n_usb2phy_sysrst_com_fastio_s, USB2PHY SYS, 1: dereset, 0: reset
	 * [3]sc_srst_n_usb2phy_portreset_fastio_s, USB2PHY PORT, 1: dereset, 0: reset
	 */
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_USB0, (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_USB0, (1 << 3));

	/* Wait until the USB2 PHY output clock is stable */
	while ((hiusb_io_read(HI_1156_USB2PHY_ADDR(FASTIO_S, CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_err("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}

	/* [7]sc_srst_n_u3drd_bus_early_fastio_s, USB3DRD Bus, 1: dereset, 0: reset */
	hiusb_io_reg_bit_set(HI_1156_FST_S_SRST_USB0, (1 << 7));
}

void hiusb_start_hcd_soc13(void)
{
	unsigned long timeout = 0;

	/* usb2.0 host */
	/* usb2.0 clock on */
	hiusb_io_reg_bit_set(HI_1155_FST_N_GATE_EN_USB2_1, HI_1156_USB2_CLK_EN);
	udelay(1);

	/* usb2 controller apb dereset */
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_USB2_1, (1 << 6));

	/* [2]usb2 phy por dereset, [0]usb2 phy apb dereset */
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_USB2_1, (1 << 0) | (1 << 2));

	/* [30]rg_pll_bypass_suspendm set 1，[28]usb2 phy default crystal oscillator clock */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG1), (1 << 30));
	hiusb_io_reg_bit_clr(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG1), (1 << 28));

	/* [9:8]select 24 MHz as the reference clock frequency, 0x0 */
	hiusb_io_reg_val_set(HI_1156_USB2PHY_ADDR(FASTIO_S, PHY_CRG0), (1 << 8) | (1 << 9), 0x0);

	/* [1]rg_pll_en_cfg set 1，[0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_S, ANA_CFG5), (1 << 0));

	/* [1]usb2phy_sys_com_srst_n dereset [3]usb2phy1_port_srst_n dereset */
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_USB2_1, (1 << 1));
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_USB2_1, (1 << 3));
	mdelay(3);

	/* Wait until the USB2 PHY output clock is stable */
	while ((hiusb_io_read(HI_1156_USB2PHY_ADDR(FASTIO_S, CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_err("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}
	/* [4]usb2 controller dereset */
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_USB2_1, (1 << 4));

	/* usb3.0 host */
	/* [0]sc_usb2phy_utmi_clk_sel_fastio_s, 0: 60M clk, 1: utmi clk */
	hiusb_io_reg_bit_set(HI_1155_FST_N_FREQ_CTRL_USB, (1 << 0));
	/* usb clock on */
	hiusb_io_reg_bit_set(HI_1155_FST_S_GATE_EN_USB0, HI_1156_USB3_CLK_EN);

	/* [9]sc_srst_n_u3hst_apb
	 * usb apb dereset
	 */
	hiusb_io_reg_bit_set(HI_1155_FST_S_SRST_USB0, (1 << 9));

	/* [2]sc_srst_n_usb2phy_por_fastio_s, usb2phy por, 1: dereset, 0: reset
	 * [0]sc_srst_n_u2phy_apb_fastio_s
	 */
	hiusb_io_reg_bit_set(HI_1155_FST_S_SRST_USB0, (1 << 2) | (1 << 0));

	/* upsphy clock on */
	hiusb_io_reg_bit_set(HI_1155_FST_N_GATE_EN_UPSPHY_1, HI_1156_USB3_UPSPHY_CLK_EN);
	/* [0]fst_s_misc_ups_phy_mode_0
	 * [1]fst_s_misc_ups_phy_mode_1
	 * [2]misc_ups_serdes_arch 0: pcie/usb, 1: serdes
	 */
	hiusb_io_reg_val_set(HI_1155_FST_N_UPS_CTL0, (1 << 0) | (1 << 1) | (1 << 2), (1 << 0));
	/* [1:0]UPSPHY multiplexing mode. 0: PCIe, reference clock 100 MHz,
	 * 1: 2.5GE reference clock 25 MHz, 2: USB3, reference clock 25 MHz
	 * [3]sc_upsphy_isnot_usb3, 0 clock from UPS PHY, 1 clock from local PLL 125 MHz clock
	 * [4]misc_usb_clk_sel0
	 */
	hiusb_io_reg_val_set(HI_1155_FST_N_UPS_CTL1,
		(1 << 3) | (1 << 4) | (1 << 1) | (1 << 0), (1 << 1) | (1 << 4));
	/* [0]misc_fs_ups_phy_iso_enb */
	hiusb_io_reg_bit_set(HI_1155_FST_N_UPS_CTL2, (1 << 0));

	/* upsphy dereset */
	hiusb_io_reg_bit_set(HI_1155_FST_N_SRST_UPSPHY_1, HI_1156_USB3_UPSPHY_RST);
	/* [30]rg_pll_bypass_suspendm */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG1), (1 << 30));
	/* [1]ck_usable_sel, CLOCK usable source select, 1: PLL, 0: LOCK DET */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, PHY_CRG0), (1 << 1));
	/* [1]rg_pll_en_cfg set 1，[0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(HI_1156_USB2PHY_ADDR(FASTIO_N, ANA_CFG5), (1 << 0));

	/* [1]sc_srst_n_usb2phy_sysrst_com_fastio_s, USB2PHY SYS, 1: dereset, 0: reset
	 * [3]sc_srst_n_usb2phy_portreset_fastio_s, USB2PHY PORT, 1: dereset, 0: reset
	 */
	hiusb_io_reg_bit_set(HI_1155_FST_S_SRST_USB0, (1 << 1));
	hiusb_io_reg_bit_set(HI_1155_FST_S_SRST_USB0, (1 << 3));

	/* Wait until the USB3 PHY output clock is stable */
	while ((hiusb_io_read(HI_1156_USB2PHY_ADDR(FASTIO_N, CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_err("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}

	/* [7]sc_srst_n_u3drd_bus_early_fastio_s, USB3DRD Bus, 1: dereset, 0: reset */
	hiusb_io_reg_bit_set(HI_1155_FST_S_SRST_USB0, (1 << 7));
}

void hiusb_start_controller_u2_only_hwsoc15(void)
{
	unsigned long timeout = 0;
	/*
	 * usb2.0 host
	 */
	/* enable usb2.0 clk */
	hiusb_io_reg_bit_set(HI_2952_FST_N_GATE_EN_USB2_1, HI_2952_USB2_CLK_MASK);
	udelay(1);

	/* usb2 contorller unreset, apb unreset */
	hiusb_io_reg_bit_set(HI_2952_FST_N_SRST_USB2_0, (1 << 6));

	/* [2]usb2 phy por unreset， [0]usb2 phy apb unreset */
	hiusb_io_reg_bit_set(HI_2952_FST_N_SRST_USB2_0, (1 << 0) | (1 << 2));

	/* [30]rg_pll_bypass_suspendm set 1，[28]usb2 phy default crystal oscillator clock */
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_ANA_CFG1), (1 << 30));
	hiusb_io_reg_bit_clr(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_ANA_CFG1), (1 << 28));

	/* [9:8]Reference clock frequency selection 20MHz, 0x1 */
	hiusb_io_reg_val_set(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_PHY_CFG0),
		(1 << 8) | (1 << 9), (1 << 8));

	/* [1]rg_pll_en_cfg set 1，[0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_ANA_CFG5), (1 << 0));

	/* [1]usb2phy_sys_com_srst_n unreset，[3]usb2phy1_port_srst_n unreset */
	hiusb_io_reg_bit_set(HI_2952_FST_N_SRST_USB2_0, (1 << 1));
	hiusb_io_reg_bit_set(HI_2952_FST_N_SRST_USB2_0, (1 << 3));
	mdelay(3);

	/* wait usb2 phy output clk stable */
	while ((hiusb_io_read(USB_PHY_ADDR(HI_2952_USB2_PHY_BASE, HI_2952_CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_info("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}
	/* [4]usb2 controller unreset */
	hiusb_io_reg_bit_set(HI_2952_FST_N_SRST_USB2_0, (1 << 4));
}

void hiusb_start_controller_u3_hwsoc15(void)
{
	unsigned long timeout = 0;
	/*
	 * usb3.0 host
	 */
	/* enable usb clk */
	hiusb_io_reg_bit_set(HI_2952_FST_S_GATE_EN_USB0, HI_2952_USB3_CLK_MASK);

	/*
	 * [9]sc_srst_n_u3hst_apb
	 * usb apb unreset
	 */
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_USB0, (1 << 9));

	/*
	 * [2]sc_srst_n_usb2phy_por_fastio_s, usb2phy por, 1: unreset, 0: reset
	 * [0]sc_srst_n_u2phy_apb_fastio_s
	 */
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_USB0, (1 << 2) | (1 << 0));

	/* USB3_PIPE clk source by UPSPHY */
	hiusb_io_reg_bit_clr(HI_2952_UPS_CTL1, (1 << 3));

	/* enable UPSPHY clk */
	hiusb_io_reg_bit_set(HI_2952_FST_S_GATE_EN_UPSPHY_0, HI_2952_USB3_PHY_CLK_MASK);

	/* UPSPHY multiplex usb3.0 mode */
	hiusb_io_reg_val_set(HI_2952_FST_S_UPS_CTL0, (1 << 1) | (1 << 0), (1 << 0));

	/* unreset UPSPHY apb */
	hiusb_io_reg_val_set(HI_2952_FST_S_SRST_UPSPHY_0, (1 << 1) | (1 << 2), (1 << 1) | (1 << 2));

	hiusb_io_reg_val_set(HI_2952_H6CC_CSR17, (1 << 0) | (1 << 1), (1 << 0));
	hiusb_io_reg_val_set(HI_2952_H6CC_CSR22, (0xffffffff >> (32 - (4))), (1 << 0));

	/* unreset ups iso */
	hiusb_io_reg_bit_set(HI_2952_FST_S_UPS_CTL2, (1 << 0));

	/* upsphy unreset */
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_UPSPHY_0, (1 << 0));

	/*
	 * [30]rg_pll_bypass_suspendm
	 */
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB3_PHY_BASE, HI_2952_ANA_CFG1), (1 << 30));
	/* [1]ck_usable_sel, CLOCK usable source select, 1: PLL, 0: LOCK DET */
	hiusb_io_reg_val_set(USB_PHY_ADDR(HI_2952_USB3_PHY_BASE, HI_2952_PHY_CFG0),
		(1 << 8) | (1 << 9) | (1 << 1), (1 << 8) | (1 << 1));
	/* [1]rg_pll_en_cfg set 1，[0]rg_pll_en_val set 1 */
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB3_PHY_BASE, HI_2952_ANA_CFG5), (1 << 1));
	hiusb_io_reg_bit_set(USB_PHY_ADDR(HI_2952_USB3_PHY_BASE, HI_2952_ANA_CFG5), (1 << 0));

	/*
	 * [1]USB2PHY SYS, 1: unreset, 0: reset
	 * [3]USB2PHY PORT, 1: unreset, 0: reset
	 */
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_USB0, (1 << 1));
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_USB0, (1 << 3));

	/* Wait until the USB3 PHY output clock is stable. */
	while ((hiusb_io_read(USB_PHY_ADDR(HI_2952_USB3_PHY_BASE, HI_2952_CKDT_STS)) & 0x1) != 1) {
		if (timeout > PLL_LOCK_TIMEOUT) {
			pr_info("timeout, clk is not stable\n");
			return;
		}
		mdelay(PLL_LOCK_DELAY);
		timeout++;
	}

	/* [7]sc_srst_n_u3drd_bus_early_fastio_s, USB3DRD Bus, 1: unreset, 0: reset */
	hiusb_io_reg_bit_set(HI_2952_FST_S_SRST_USB0, (1 << 7));
}

void hiusb_start_hcd_hwsoc15(void)
{
	struct device_node *node = NULL;
	struct property *node_property = NULL;

	hiusb_start_controller_u2_only_hwsoc15();
	hiusb_start_controller_u3_hwsoc15();

	/* The 2952 u2 only controller does not support acp, but the u3 controller supports acp. */
	if (g_usb_acp_enable) {
		/*
		 * cache attribute：
		 * rcache/wcache :
		 * 0xb/0x7: Write-back No-allocate
		 * 0xf/0x7: Write-back Read-allocate
		 * 0xb/0xf: Write-back Write-allocate
		 * 0xf/0xf: Write-back Read and Write-allocate
		 */

		/*
		 * config usb3.0 acp cache attribute,
		 * [21]rcache Attribute control register, [19:16]rcache ;
		 * [12]wcacheAttribute control register, [11:8]wcache
		 */
		hiusb_io_reg_val_set(HI_2952_USB3_CTRL_CTRL2,
			HI_2952_USB3_XM_ARCACHE_SEL | HI_2952_USB3_XM_ARCACHE,
			HI_2952_USB3_XM_ARCACHE_SEL | (0xb << 16));
		hiusb_io_reg_val_set(HI_2952_USB3_CTRL_CTRL2,
			HI_2952_USB3_XM_AWCACHE_SEL | HI_2952_USB3_XM_AWCACHE,
			HI_2952_USB3_XM_AWCACHE_SEL | (0x7 << 8));
		hiusb_io_reg_bit_set(HI_2952_REG_ACP, (1 << 3));
		pr_info("2952 USB ACP enabled");
	} else {
		node = of_find_node_by_name(NULL, "usb1_xhci");
		if (node == NULL)
			pr_info("find usb node failed\n");
		node_property = of_find_property(node, "dma-coherent", NULL);
		if (node_property == NULL)
			pr_info("find dma-coherent property failed\n");
		(void)of_remove_property(node, node_property);
		pr_info("hwsoc15 USB ACP disabled\n");
	}
}

void hiusb_start_hcd(void)
{
	enum HW_CHIP_ID_E hw_chip_id;

	hw_chip_id = get_chip_id_ont();
	if ((hw_chip_id != HW_CHIP_ID_NONE_E) &&
		(atomic_add_return(1, &dev_open_cnt) == 1)) {
		switch (hw_chip_id) {
		case HW_CHIP_ID_5115S_E:
		case HW_CHIP_ID_5115H_E:
		case HW_CHIP_ID_5115T_E:
			hiusb_start_hcd_5115();
			break;
		case HW_CHIP_ID_5116H_E:
		case HW_CHIP_ID_5116T_E:
		case HW_CHIP_ID_5116TV5_E:
			/*5116 */
			hiusb_start_hcd_5116();
			break;
		case HW_CHIP_ID_5118_E:
		case HW_CHIP_ID_5118V2_E:
			hiusb_start_hcd_5118();
			break;
		case HW_CHIP_ID_5117H_E:
			hiusb_start_hcd_5117h();
			break;
		case HAL_CHIP_ID_5117PV5:
		case HW_CHIP_ID_5117P_E:
			hiusb_start_hcd_hwsoc1();
			break;
		case HW_CHIP_ID_5117V_E:
			hiusb_start_hcd_hwsoc3();
			break;
		case HW_CHIP_ID_5610T_E:
		case HW_CHIP_ID_5610H_E:
			if (hi_usb_5610_map_reg() != 0) {
				return;
			}
			if (hw_chip_id == HW_CHIP_ID_5610T_E)
				hi_usb_5610T_start_hcd();
			break;
		case HW_CHIP_ID_5117L_E:
			hiusb_start_hcd_hwsoc2();
			break;
		case HAL_CHIP_ID_5182HV5:
		case HW_CHIP_ID_5182H_E:
			hiusb_start_hcd_hwsoc4();
			break;
		case HAL_CHIP_ID_5182T:
			hiusb_start_hcd_hwsoc8();
			break;
		case HAL_CHIP_ID_1156H:
		case HAL_CHIP_ID_1156E:
			hiusb_start_hcd_soc12();
			break;
		case HAL_CHIP_ID_1155H:
			hiusb_start_hcd_soc13();
			break;
		case HAL_CHIP_ID_2952H:
			hiusb_start_hcd_hwsoc15();
			break;
		default:
			break;
		}
	}
}
EXPORT_SYMBOL_GPL(hiusb_start_hcd);

void hiusb_stop_hcd_5115(void)
{
	unsigned int reg;
	unsigned long flags;

	local_irq_save(flags);
	reg = readl(g_usb_5115_reg_ctrl.PERI_PEREN);
	reg &= ~USB_HCLK_EN;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PEREN);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PEREN1);
	reg &= ~USB_CLK_EN;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PEREN1);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL36);
	reg &= ~USB_PORT1_RST;
	reg &= ~USB_PORT0_RST;
	reg &= ~USB_CTRL_RST;
	reg &= ~USB_SRST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL36);

	reg = readl(g_usb_5115_reg_ctrl.PERI_PERCTRL39);
	reg &= ~USB_PHY1_RST;
	reg &= ~USB_PHY0_RST;
	writel(reg, g_usb_5115_reg_ctrl.PERI_PERCTRL39);

	local_irq_restore(flags);
	hiusb_5115_unmap_reg();
	pr_info("hiusb_stop_hcd successful(5115)!\n");
	udelay(100);
}

void hiusb_stop_hcd_5116h(void)
{
	unsigned int reg;
	unsigned long flags;

	local_irq_save(flags);
	reg = readl(g_usb_5116_reg_ctrl.IO_SEL0);  // io_mux pin mux release
	reg |= 0x60000;
	writel(reg, g_usb_5116_reg_ctrl.IO_SEL0);

	reg = readl(g_usb_5116_reg_ctrl.SC_PERCTRL38);  // usb phy insulate enable
	reg |= 0x1;
	writel(reg, g_usb_5116_reg_ctrl.SC_PERCTRL38);

	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock disable
	reg &= ~0x1000;
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy reset
	reg &= ~0x8000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(3);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy port reset
	reg &= ~0x10000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset
	reg &= ~0x4000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	local_irq_restore(flags);
	hiusb_hwsoc4_unmap_reg();

	pr_info("hiusb_stop_hcd successful(5116)!\n");
}

void hiusb_stop_hcd_5116t(void)
{
	unsigned int reg;
	unsigned long flags;

	local_irq_save(flags);
	reg = readl(g_usb_5116_reg_ctrl.SC_PERCTRL38);  // usb phy insulate enable
	reg |= 0x1;
	writel(reg, g_usb_5116_reg_ctrl.SC_PERCTRL38);

	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock disable
	reg &= ~0x1000;
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy reset
	reg &= ~0x10001000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(3);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy port reset
	reg &= ~0x20002000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset
	reg &= ~0x4000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	local_irq_restore(flags);
	hiusb_hwsoc4_unmap_reg();

	pr_info("hiusb_stop_hcd successful(5116)!\n");
}

void hiusb_stop_hcd_5118(void)
{
	unsigned int reg;
	unsigned long flags;

	local_irq_save(flags);
	// usb controller reset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<14);  // usb controller reset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	udelay(5);    // logic suggest 1us

	// usb3 phy port reset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<29);  // port0 usb3 port reset
	BIT_CLR(reg, 0x1<<31);  // port1 usb3 port reset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	udelay(15);    // logic suggest 10us

	// usb3 phy reset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<28);  // port0 usb3 phy reset
	BIT_CLR(reg, 0x1<<30);  // port1 usb3 phy reset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	udelay(15);    // logic suggest 10us

	// usb2 phy port reset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<16);  // port0 usb2 port reset
	BIT_CLR(reg, 0x1<<13);  // port1 usb2 port reset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);

	// usb2 phy reset
	reg = readl(g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<15);  // port0 usb2 phy reset
	BIT_CLR(reg, 0x1<<12);  // port1 usb2 phy reset
	writel(reg, g_usb_5118_reg_ctrl.SC_RST_CTRL0);
	udelay(40);    // logic suggest 35us

	// read clock state reg
	reg = readl(g_usb_5118_reg_ctrl.SC_PER_CLK_ST1);
	BIT_SET(reg, 0x1<<12);  // open usb controller clock
	BIT_SET(reg, 0x1<<16);  // open usb port0 usb2 reference clock
	BIT_SET(reg, 0x1<<17);  // open usb port1 usb2 reference clock
	BIT_SET(reg, 0x1<<18);  // open usb port0 usb3 reference clock
	BIT_SET(reg, 0x1<<19);  // open usb port1 usb3 reference clock
	writel(reg, g_usb_5118_reg_ctrl.SC_PER_CLK_DIS1);

	local_irq_restore(flags);
	hiusb_5118_unmap_reg();

	pr_info("hiusb_stop_hcd successful(5118)!\n");
}

void hiusb_stop_hcd_5117l(void)
{
	unsigned int reg;
	unsigned long flags;

	local_irq_save(flags);
	/* pin to gpio */
	reg = readl(g_usb_5116_reg_ctrl.IO_SEL0);  // io_mux pin mux release
	reg |= 0x18000000;
	writel(reg, g_usb_5116_reg_ctrl.IO_SEL0);
	udelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy reset bit15
	reg &= ~0x8000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	udelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb phy port reset bit16
	reg &= ~0x10000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	udelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset bit14
	reg &= ~0x4000;
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	udelay(2);

	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock enable bit12
	reg &= ~0x1000;
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);
	udelay(2);

	local_irq_restore(flags);
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	iounmap(g_usb_5116_reg_ctrl.SC_RST_CTRL1);
	iounmap(g_usb_5116_reg_ctrl.SC_PEREN1);
	iounmap(g_usb_5116_reg_ctrl.IO_SEL0);

	pr_info("hiusb_stop_hcd successful(5117L)!\n");
}

void hiusb_stop_hcd_5182(void)
{
	unsigned int reg;
	unsigned long flags;

	/* logically it can not be sure that this stop can be correctly processed */
	pr_info("hiusb_stop_hcd begin(5182H)!\n");

	local_irq_save(flags);
	/* 'SC_PEREN1 usb_ctrl_clk_gate_en    0x14880020 bit22 16~19*/
	reg = readl(g_usb_5116_reg_ctrl.SC_PEREN1);  // usb clock enable
	BIT_CLR(reg, 0x1<<21);  // open usb controller clock
	BIT_CLR(reg, 0x1<<22);  // open usb controller clock
	BIT_CLR(reg, 0x1<<16);  // open usb port0 usb2 reference clock
	BIT_CLR(reg, 0x1<<17);  // open usb port1 usb2 reference clock
	BIT_CLR(reg, 0x1<<18);  // open usb port0 usb3 reference clock
	BIT_CLR(reg, 0x1<<19);  // open usb port1 usb3 reference clock
	writel(reg, g_usb_5116_reg_ctrl.SC_PEREN1);

	mdelay(2);

	// usb2 phy unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<24);  // port0 usb2 phy unreset
	BIT_CLR(reg, 0x1<<28);  // port1 usb2 phy unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	// usb2 phy port unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<25);  // port0 usb2 port unreset
	BIT_CLR(reg, 0x1<<29);  // port1 usb2 port unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	// usb3 phy unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<26);  // port0 usb3 phy unreset
	BIT_CLR(reg, 0x1<<30);  // port1 usb3 phy unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	mdelay(2);

	// usb3 phy port unreset
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	BIT_CLR(reg, 0x1<<27);  // port0 usb3 port unreset
	BIT_CLR(reg, 0x1<<31);  // port1 usb3 port unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);

	/* 'SC_RST_CTRL0 usb_srst_n 0x14880034 bit23 */
	reg = readl(g_usb_5116_reg_ctrl.SC_RST_CTRL0);  // usb host reset release
	BIT_CLR(reg, 0x1<<23);  // usb controller unreset
	BIT_CLR(reg, 0x1<<22);  // usb controller unreset
	writel(reg, g_usb_5116_reg_ctrl.SC_RST_CTRL0);
	mdelay(2);

	local_irq_restore(flags);
	hiusb_hwsoc4_unmap_reg();
	pr_info("hiusb_stop_hcd successful(5182H)!\n");
}

void hiusb_stop_hcd_soc8(void)
{
	pr_info("hiusb_stop_hcd begin(SOC8)!\n");

	/* 'SC_RST_CTRL0 controller reset */
	hiusb_io_reg_bit_clr(0x14880034, USB_CTRL_UNRESET_82T);
	mdelay(1);

	/* usb phy port reset */
	hiusb_io_reg_bit_clr(0x14880034, USB_PHY_PORT_UNRESET_82T);
	mdelay(1);

	/* usb phy reset */
	hiusb_io_reg_bit_clr(0x14880034, USB_PHY_POR_UNRESET_82T);
	mdelay(1);

	/* usb phy0 and phy1 clock disable */
	hiusb_io_reg_bit_clr(0x148802D4, USB_PHY_CLK_ENABLE_82T);
	mdelay(1);

	/* usb apb reset */
	hiusb_io_reg_bit_set(0x14880034, USB_APB_UNRESET_82T);

	/* 'SC_PEREN1 usb_ctrl_clk_gate_dis    0x14880024 bit17~22 5~6 */
	hiusb_io_write(0x14880024, USB_CLK_ENABLE_82T);
	mdelay(1);

	pr_info("hiusb_stop_hcd successful(SOC8)!\n");
}

void hiusb_stop_hcd_soc12(void)
{
	pr_info("hiusb_stop_hcd begin(1156)!\n");

	if (g_usb_xhci_gen2_force) {
		/* reset USB3 */
		hiusb_io_reg_bit_clr(HI_1156_FST_S_SRST_USB0, HI_1156_USB3_RST);

		/* stop USB3 clock */
		hiusb_io_reg_bit_clr(HI_1156_FST_S_GATE_EN_USB0, HI_1156_USB3_CLK_EN);

		/* reset UPSPHY */
		hiusb_io_reg_bit_clr(HI_1156_FST_S_SRST_UPSPHY_0, HI_1156_USB3_UPSPHY_RST);

		/* stop UPSPHY clock */
		hiusb_io_reg_bit_clr(HI_1156_FST_S_GATE_EN_UPSPHY_0, HI_1156_USB3_UPSPHY_CLK_EN);
	} else {
		/* reset USB2 */
		hiusb_io_reg_bit_clr(HI_1156_FST_N_SRST_USB2_1, HI_1156_USB2_RST);

		/* stop USB2 related clock */
		hiusb_io_reg_bit_clr(HI_1156_FST_N_GATE_EN_USB2_1, HI_1156_USB2_CLK_EN);
	}

	pr_info("hiusb_stop_hcd successful(1156)!\n");
}

void hiusb_stop_hcd_soc13(void)
{
	pr_info("hiusb_stop_hcd begin(1155)!\n");

	/* reset USB2 */
	hiusb_io_reg_bit_clr(HI_1155_FST_N_SRST_USB2_1, HI_1156_USB2_RST);

	/* stop USB2 clock */
	hiusb_io_reg_bit_clr(HI_1155_FST_N_GATE_EN_USB2_1, HI_1156_USB2_CLK_EN);

	/* reset USB3 */
	hiusb_io_reg_bit_clr(HI_1155_FST_S_SRST_USB0, HI_1156_USB3_RST);

	/* stop USB3 related clock */
	hiusb_io_reg_bit_clr(HI_1155_FST_S_GATE_EN_USB0, HI_1156_USB3_CLK_EN);

	/* reset UPSPHY */
	hiusb_io_reg_bit_clr(HI_1155_FST_N_SRST_UPSPHY_1, HI_1156_USB3_UPSPHY_RST);

	/* stop UPSPHY clock */
	hiusb_io_reg_bit_clr(HI_1155_FST_N_GATE_EN_UPSPHY_1, HI_1156_USB3_UPSPHY_CLK_EN);

	pr_info("hiusb_stop_hcd successful(1155)!\n");
}

void hiusb_stop_hcd_hwsoc15(void)
{
	pr_info("hiusb_stop_hcd begin(hwsoc15)!\r\n");

	/* reset USB2 PHY + Host */
	hiusb_io_reg_bit_clr(HI_2952_FST_N_SRST_USB2_0, HI_2952_USB2_RST_MASK);

	/* disable USB2 clk PHY + Host */
	hiusb_io_reg_bit_clr(HI_2952_FST_N_GATE_EN_USB2_1, HI_2952_USB2_CLK_MASK);

	/* reset USB3 PHY */
	hiusb_io_reg_bit_clr(HI_2952_FST_S_SRST_UPSPHY_0, HI_2952_USB3_PHY_RST_MASK);

	/* disable USB3 PHY clk */
	hiusb_io_reg_bit_clr(HI_2952_FST_S_GATE_EN_UPSPHY_0, HI_2952_USB3_PHY_CLK_MASK);

	/* reset USB3 Host */
	hiusb_io_reg_bit_clr(HI_2952_FST_S_SRST_USB0, HI_2952_USB3_RST_MASK);

	/* disable USB3 Host clk */
	hiusb_io_reg_bit_clr(HI_1155_FST_S_GATE_EN_USB0, HI_2952_USB3_CLK_MASK);

	pr_info("hiusb_stop_hcd successful(hwsoc15)!\r\n");
}

void hiusb_stop_hcd(void)
{
	enum HW_CHIP_ID_E hw_chip_id;

	hw_chip_id = get_chip_id_ont();
	if (hw_chip_id != HW_CHIP_ID_NONE_E) {
		if (atomic_sub_return(1, &dev_open_cnt) == 0) {
			switch (hw_chip_id) {
			case HW_CHIP_ID_5115S_E:
			case HW_CHIP_ID_5115H_E:
			case HW_CHIP_ID_5115T_E:
				hiusb_stop_hcd_5115();
				break;
			case HW_CHIP_ID_5116H_E:
				/* 5116H */
				hiusb_stop_hcd_5116h();
				break;
			case HW_CHIP_ID_5116T_E:
			case HW_CHIP_ID_5116TV5_E:
				/* 5116T */
				hiusb_stop_hcd_5116t();
				break;
			case HW_CHIP_ID_5118_E:
			case HW_CHIP_ID_5118V2_E:
				hiusb_stop_hcd_5118();
				break;
			case HW_CHIP_ID_5610H_E:
			case HW_CHIP_ID_5610T_E:
				/* 5610H no process */
				if (hw_chip_id == HW_CHIP_ID_5610T_E)
					hi_usb_5610T_stop_hcd();
				break;
			case HW_CHIP_ID_5117L_E:
				/* 5117L inherite SD5116H */
				hiusb_stop_hcd_5117l();
				break;
			case HW_CHIP_ID_5182H_E:
			case HAL_CHIP_ID_5182HV5:
				/* 5182H */
				hiusb_stop_hcd_5182();
				break;
			case HAL_CHIP_ID_5182T:
				hiusb_stop_hcd_soc8();
				break;
			case HAL_CHIP_ID_1156H:
			case HAL_CHIP_ID_1156E:
				hiusb_stop_hcd_soc12();
				break;
			case HAL_CHIP_ID_1155H:
				hiusb_stop_hcd_soc13();
				break;
			case HAL_CHIP_ID_2952H:
				hiusb_stop_hcd_hwsoc15();
				break;
			default:
				break;
			}
		}
	}
}
EXPORT_SYMBOL_GPL(hiusb_stop_hcd);

static int __init hiusb_sd511x_init(void)
{
	hiusb_start_hcd();
	return 0;
}
module_init(hiusb_sd511x_init);

static void __exit hiusb_sd511x_exit(void)
{
	hiusb_stop_hcd();
}
module_exit(hiusb_sd511x_exit);
MODULE_LICENSE("GPL");
